import { ForbiddenException } from '@nestjs/common'

import { envBoolean } from '~/global/env'
import { MenuEntity } from '~/modules/system/menu/menu.entity'
import { isExternal } from '~/utils/is.util'

import { uniqueSlash } from './tool.util'

// 前端期望的 meta 结构
type SvgName = string
type ElementPlusIconsName = string

export interface RouteMeta {
  /** 在侧边栏和面包屑中展示的名字 */
  title?: string
  /** svg 图标名（优先） */
  svgIcon?: SvgName
  /** Element Plus 图标名 */
  elIcon?: ElementPlusIconsName
  /** 默认 false，true 时在侧边栏隐藏 */
  hidden?: boolean
  /** 可访问该路由的角色列表 (已移除，由权限中心/前端控制) */
  /** 默认 true，false 时面包屑不显示 */
  breadcrumb?: boolean
  /** 默认 false，true 时固定在 tags-view */
  affix?: boolean
  /** 是否总是显示父路由 */
  alwaysShow?: boolean
  /** 进入路由时高亮的侧边栏 path */
  activeMenu?: string
  /** 是否缓存该页面 */
  keepAlive?: boolean
}

export interface RouteRecordRaw {
  id: number
  path: string
  name: string
  component?: string
  redirect?: string
  meta: RouteMeta
  children?: RouteRecordRaw[]
}

function createRoute(menu: MenuEntity, _isRoot: boolean): RouteRecordRaw {
  // 复用 createMenuMeta，避免重复构建 meta 结构
  const commonMeta: RouteMeta = createMenuMeta(menu)

  if (isExternal(menu.path)) {
    return {
      id: menu.id,
      path: menu.path,
      // component: 'IFrame',
      name: menu.name,
      meta: { ...commonMeta },
    }
  }

  // 目录
  if (menu.type === 0) {
    return {
      id: menu.id,
      path: menu.path,
      component: menu.component,
      name: menu.name,
      meta: { ...commonMeta },
    }
  }

  return {
    id: menu.id,
    path: menu.path,
    name: menu.name,
    component: menu.component,
    meta: { ...commonMeta },
  }
}

function filterAsyncRoutes(menus: MenuEntity[], parentRoute: MenuEntity): RouteRecordRaw[] {
  const res: RouteRecordRaw[] = []

  menus.forEach((menu) => {
    if (menu.type === 2 || !menu.status) {
      // 如果是权限或禁用直接跳过
      return
    }
    // 根级别菜单渲染
    let realRoute: RouteRecordRaw

    const genFullPath = (path: string, parentPath) => {
      return uniqueSlash(path.startsWith('/') ? path : `/${parentPath}/${path}`)
    }

    if (!parentRoute && !menu.parentId && menu.type === 1) {
      // 根菜单
      realRoute = createRoute(menu, true)
    }
    else if (!parentRoute && !menu.parentId && menu.type === 0) {
      // 目录
      const childRoutes = filterAsyncRoutes(menus, menu)
      realRoute = createRoute(menu, true)
      if (childRoutes && childRoutes.length > 0) {
        realRoute.redirect = genFullPath(childRoutes[0].path, realRoute.path)
        realRoute.children = childRoutes
      }
    }
    else if (
      parentRoute
      && parentRoute.id === menu.parentId
      && menu.type === 1
    ) {
      // 子菜单
      realRoute = createRoute(menu, false)
    }
    else if (
      parentRoute
      && parentRoute.id === menu.parentId
      && menu.type === 0
    ) {
      // 如果还是目录，继续递归
      const childRoutes = filterAsyncRoutes(menus, menu)
      realRoute = createRoute(menu, false)
      if (childRoutes && childRoutes.length > 0) {
        realRoute.redirect = genFullPath(childRoutes[0].path, realRoute.path)
        realRoute.children = childRoutes
      }
    }
    // add curent route
    if (realRoute)
      res.push(realRoute)
  })
  return res
}

export function generatorRouters(menus: MenuEntity[]) {
  return filterAsyncRoutes(menus, null)
}

// 获取所有菜单以及权限（简洁版）
// - menus: 全量菜单（未组织成树）
// - parentMenu: 递归时的父节点（null 表示根级）
// 返回值：符合前端期望的菜单项数组，每项都包含 `meta` 字段
function filterMenuToTable(menus: MenuEntity[], parentMenu: MenuEntity | null) {
  return menus.reduce((acc: any[], menu) => {
    const isRoot = !parentMenu && !menu.parentId
    const isChild = parentMenu && parentMenu.id === menu.parentId

    // 只有下面两类会生成菜单项：
    // 1. 根级别的菜单(type===1) 或 根级目录(type===0)
    // 2. 父节点下的子菜单(type===1) 或 子目录(type===0)
    // 注意：type===2（权限项）不应加入菜单树
    const shouldInclude = (isRoot && (menu.type === 1 || menu.type === 0))
      || (isChild && (menu.type === 1 || menu.type === 0))

    if (!shouldInclude)
      return acc

    const children = filterMenuToTable(menus, menu)
    const realMenu: any = { ...menu }
    if (children && children.length > 0)
      realMenu.children = children

    realMenu.pid = menu.id
    // 注入 meta，保证前端收到的数据结构一致
    realMenu.meta = createMenuMeta(menu)

    acc.push(realMenu)
    return acc
  }, [])
}

export function generatorMenu(menu: MenuEntity[]) {
  return filterMenuToTable(menu, null)
}

// 为菜单表项生成 meta 字段，保证前端接收时每个项都有 meta
function createMenuMeta(menu: MenuEntity) {
  return {
    title: menu.name || undefined,
    svgIcon: (menu.icon as unknown as SvgName) || undefined,
    elIcon: undefined,
    hidden: menu.show === 0,
    // roles 字段已从 meta 中移除，权限由后端权限接口下发或前端维护
    breadcrumb: true,
    affix: false,
    alwaysShow: false,
    activeMenu: menu.activeMenu || undefined,
    keepAlive: !!menu.keepAlive,
  } as RouteMeta
}

/** 检测是否为演示环境, 如果为演示环境，则拒绝该操作 */
export function checkIsDemoMode() {
  if (envBoolean('IS_DEMO'))
    throw new ForbiddenException('演示模式下不允许操作')
}
